package org.example.entity;

import cn.hutool.core.thread.ThreadUtil;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Log4j
public class Vehicle implements Runnable {

    /**
     * 车辆编号
     */
    static AtomicInteger id = new AtomicInteger(1);

    /**
     * 车辆名称
     */
    public final String name;

    /**
     * 车辆等待时间
     */
    private final Integer residenceTime;

    /**
     * 要进入的停车场
     */
    private final ParkingLot parkingLot;

    /**
     * 控制每次车辆同时抢夺进入
     */
    private final CountDownLatch latch;


    public Vehicle(ParkingLot parkingLot, CountDownLatch latch) {
        this.name = "vehicle" + id.getAndIncrement();
        this.residenceTime = new Random().nextInt(5) + 10;
        this.parkingLot = parkingLot;
        this.latch = latch;
    }

    @SneakyThrows(InterruptedException.class)
    @Override
    public void run() {
        //1、等待进入停车场
        waitEntryParking();
        latch.await();

        //2、尝试进入停车场
        loopTryEntryPacking();

        //3、车辆在停车场停留
        stayParking();

        //4、正在离开停车场
        parkingLot.exitParking(this);

    }

    /**
     * 车辆循环等待被调度进入停车场
     */
    private void loopTryEntryPacking() {
        boolean isEnter = parkingLot.tryEntryParking(this);
        while (!isEnter) {
            ThreadUtil.sleep(5, TimeUnit.SECONDS);
            isEnter = parkingLot.tryEntryParking(this);
        }
    }

    /**
     * 车辆在停车场外等待调度进入
     */
    private void waitEntryParking() {
        log.info(this.name + ": wait entry");
    }

    /**
     * 车辆在停车场中停留
     */
    private void stayParking() {
        try {
            log.info(this.name + ": stay");
            TimeUnit.SECONDS.sleep(residenceTime);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

}
